package com.semidata.trp.monitor.job;

import io.netty.handler.codec.http.Cookie;
import io.netty.handler.codec.http.CookieDecoder;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.QueryStringEncoder;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import com.semidata.rtd.core.http.server.HttpSession;
import com.semidata.rtd.core.log.Logger;
import com.semidata.trp.monitor.config.Config;

public class MonitorRequest {

	private static final String USERID_KEY = "smid";

	public enum Type {
		IMP, CLK
	}

	private Integer orgId;
	private Integer positionId;
	private Integer resourceId;
	private Integer strategyId;
	private List<Integer> materialId;
	private Integer mediaType;
	private String userId;
	private Long time;
	private Double price;
	private String ip;
	private String landingPage;
	private Type type;
	private String log;
	private String keyWord1;
	private String keyWord2;
	private String keyWord3;

	public MonitorRequest(HttpSession session) {

		try {
			String requestUrl = session.getRequest().getUri();
			QueryStringDecoder decoder = new QueryStringDecoder(requestUrl);

			Config config = Config.getConfig();

			String path = decoder.path();
			QueryStringEncoder encoder = new QueryStringEncoder(path);

			if (!path.endsWith("/"))
				path += "/";
			if (path.equals(config.getImpressionPrefix())) {
				type = Type.IMP;
			} else if (path.equals(config.getClickPrefix())) {
				type = Type.CLK;
			} else {
				throw new RuntimeException("unknown monitor url: " + requestUrl);
			}

			ip = decoder.parameters().get("i").get(0);
			encoder.addParam("i", ip.toString());

			List<String> userList = decoder.parameters().get("u");
			if (userList != null && !userList.isEmpty())
				userId = userList.get(0);
			if (userId != null && userId.isEmpty())
				userId = null;

			if (userId == null)
				userId = getUserId(session);

			encoder.addParam("u", userId);

			orgId = Integer.parseInt(decoder.parameters().get("a").get(0));
			encoder.addParam("a", orgId.toString());

			positionId = Integer.parseInt(decoder.parameters().get("p").get(0));
			encoder.addParam("p", positionId.toString());

			resourceId = Integer.parseInt(decoder.parameters().get("r").get(0));
			encoder.addParam("r", resourceId.toString());

			strategyId = Integer.parseInt(decoder.parameters().get("s").get(0));
			encoder.addParam("s", strategyId.toString());

			mediaType = Integer.parseInt(decoder.parameters().get("mt").get(0));
			encoder.addParam("mt", mediaType.toString());

			String materiaList = decoder.parameters().get("m").get(0);
			String []materials = materiaList.split("_");
			materialId = new ArrayList<Integer>();
			for(int i = 0;i < materials.length;i++){
				materialId.add(Integer.parseInt(materials[i]));
			}
			//materialId = Integer.parseInt(decoder.parameters().get("m").get(0));
			encoder.addParam("m", materiaList.toString());

			time = Long.parseLong(decoder.parameters().get("t").get(0));
			encoder.addParam("t", time.toString());

			price = Double.parseDouble(decoder.parameters().get("b").get(0));
			encoder.addParam("b", price.toString());

			if (decoder.parameters().get("k1") != null
					&& decoder.parameters().get("k2") != null
					&& decoder.parameters().get("k3") != null) {
				keyWord1 = decoder.parameters().get("k1").get(0);
				keyWord2 = decoder.parameters().get("k2").get(0);
				keyWord3 = decoder.parameters().get("k3").get(0);
			} else {
				keyWord1 = "";
				keyWord2 = "";
				keyWord3 = "";
			}
			encoder.addParam("k1", keyWord1);
			encoder.addParam("k2", keyWord2);
			encoder.addParam("k3", keyWord3);

			encoder.addParam("c",
					new Long(System.currentTimeMillis()).toString());

			if (type == Type.CLK) {
				landingPage = decoder.parameters().get("o").get(0);
				if (landingPage == null)
					throw new Exception();
				encoder.addParam("o", landingPage);
			} else {
				landingPage = null;
			}

			if (userId == null || ip == null)
				throw new Exception();

			log = encoder.toString();

		} catch (Exception e) {
			throw new RuntimeException("bad url");
		}
	}

	public int getOrgId() {
		return orgId;
	}

	public int getPositionId() {
		return positionId;
	}

	public int getResourceId() {
		return resourceId;
	}

	public int getStrategyId() {
		return strategyId;
	}

	public List<Integer> getMaterialId() {
		return materialId;
	}

	public String getUserId() {
		return userId;
	}

	public long getTime() {
		return time;
	}

	public double getPrice() {
		return price;
	}

	public String getIp() {
		return ip;
	}

	public String getLandingPage() {
		return landingPage;
	}

	public Type getType() {
		return type;
	}

	public String getLogString() {
		return log;
	}

	private String getUserId(HttpSession session) {
		Set<Cookie> cookies;
		String cookieString = session.getRequest().headers()
				.get(HttpHeaders.Names.COOKIE);
		cookies = cookieString == null ? new TreeSet<Cookie>() : CookieDecoder
				.decode(cookieString);

		for (Cookie cookie : cookies) {
			if (cookie.getName().equals(USERID_KEY))
				return cookie.getValue();
		}

		return generateUserId(session);
	}

	private String generateUserId(HttpSession session) {
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.update(ip.getBytes());
			md5.update(Long.valueOf(System.currentTimeMillis()).toString()
					.getBytes());
			md5.update(Double.valueOf(Math.random()).toString().getBytes());
			String userId = toB64(md5.digest());
			session.getResponse().addCookie(USERID_KEY, userId);
			return userId;
		} catch (NoSuchAlgorithmException e) {
			return null;
		}
	}

	private String toB64(byte[] bytes) {

		char[] b64 = { '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8',
				'9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
				'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
				'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
				'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
				'v', 'w', 'x', 'y', 'z' };

		byte[] newBytes = new byte[9];

		for (int i = 0; i < 9; i++) {
			newBytes[i] = 0;
		}

		for (int i = 0; i < bytes.length; i++) {
			newBytes[i % 9] ^= bytes[i];
		}

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < 9; i += 3) {

			int index;
			index = (bytes[i] & 0xff) >> 2;
			sb.append(b64[index]);

			index = (bytes[i] & 0x3) << 4 | (bytes[i + 1] & 0xff) >> 4;
			sb.append(b64[index]);

			index = (bytes[i + 1] & 0x0f) << 2 | (bytes[i + 2] & 0xff) >> 6;
			sb.append(b64[index]);

			index = (bytes[i + 2] & 0x3f);
			sb.append(b64[index]);
		}
		return sb.toString();
	}

	public String getKeyWord() {
		return keyWord1 + "_" + keyWord2 + "_" + keyWord3;
	}

	public void setKeyWord1(String keyWord1) {
		this.keyWord1 = keyWord1;
	}

	public void setKeyWord2(String keyWord2) {
		this.keyWord2 = keyWord2;
	}

	public void setKeyWord3(String keyWord3) {
		this.keyWord3 = keyWord3;
	}

	public Integer getMediaType() {
		return mediaType;
	}

	public void setMediaType(Integer mediaType) {
		this.mediaType = mediaType;
	}
	


	public static void main(String[] args) {
		String abc = "135";
		String [] a = abc.split("_");
		for(int i = 0;i < a.length;i++)
			System.out.println(a[i]);
	}

}
